package lib.bone.admin.controller.system;

import cn.dev33.satoken.annotation.SaCheckPermission;
import cn.dev33.satoken.annotation.SaCheckRole;
import cn.dev33.satoken.stp.StpUtil;
import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.bean.copier.CopyOptions;
import cn.hutool.core.io.FileUtil;
import cn.hutool.core.lang.Validator;
import cn.hutool.extra.pinyin.PinyinUtil;
import com.alibaba.excel.EasyExcel;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lib.bone.access.module.post.NepuPostDAO;
import lib.bone.access.module.post.NepuPostService;
import lib.bone.access.module.post.domain.NepuPost;
import lib.bone.admin.anno.WebLog;
import lib.bone.admin.constant.MethodTypeConst;
import lib.bone.admin.controller.system.dto.UserExportVO;
import lib.bone.admin.domain.vo.DeptUserTreeVO;
import lib.bone.admin.listener.UserDeleteListener;
import lib.bone.admin.listener.UserUpdateImportListener;
import lib.bone.common.constant.ResponseCodeConst;
import lib.bone.common.core.domain.ResponseDTO;
import lib.bone.system.dao.SysDeptDAO;
import lib.bone.system.dao.SysUserDAO;
import lib.bone.system.domain.dto.user.*;
import lib.bone.system.domain.entity.SysDept;
import lib.bone.system.domain.entity.SysUser;
import lib.bone.system.domain.vo.SysDeptVO;
import lib.bone.system.domain.vo.SysUserBasic;
import lib.bone.system.domain.vo.SysUserVO;
import lib.bone.system.domain.vo.UserBaseVO;
import lib.bone.system.listener.UserImportListener;
import lib.bone.system.service.SysDeptService;
import lib.bone.system.service.SysRoleService;
import lib.bone.system.service.SysUserRoleService;
import lib.bone.system.service.SysUserService;

import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.domain.Example;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.domain.Sort;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;
import springfox.documentation.annotations.ApiIgnore;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.IOException;
import java.text.ParseException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author: kindear
 */
@RestController
@RequestMapping("system")
@Api(tags = "系统用户管理")
@Slf4j
public class SysUserController {
    @Autowired
    SysUserService sysUserService;

    @Autowired
    SysDeptService sysDeptService;

    @Autowired
    SysUserRoleService sysUserRoleService;

    @Autowired
    SysRoleService sysRoleService;

    @Autowired
    NepuPostService nepuPostService;


    @Autowired
    SysUserDAO sysUserDAO;

    @Autowired
    SysDeptDAO sysDeptDAO;

    @Autowired
    NepuPostDAO nepuPostDAO;

    @Value("${file-upload-service.path}")
    private String fileParentPath;


    @PostMapping("users/update/import")
    @ApiOperation(value = "用户更新导入",notes = "")
    public ResponseDTO updateUsers(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), UserUpdateImportDTO.class, new UserUpdateImportListener(sysUserService,sysDeptService,nepuPostService)).sheet().doRead();
        return ResponseDTO.succMsg("写入成功");
    }

    @GetMapping("users/update/password")
    @ApiOperation(value = "重置初始密码",notes = "")
    public ResponseDTO updatePassword() {
        SysUser sysUser = new SysUser();
        sysUser.setPassword("123456");
        Example<SysUser> example = Example.of(sysUser);
        List<SysUser> list = sysUserDAO.findAll(example);
        for (SysUser user : list) {
            user.setPassword("Dyjx123456");
            sysUserService.updateOne(user);
        }
        return ResponseDTO.succData("修改完成！");

    }

    @PostMapping("users/update/delete")
    @ApiOperation(value = "用户删除",notes = "")
    public ResponseDTO deleteUsers(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), UserdeleteDTO.class, new UserDeleteListener(sysUserService,sysDeptService,nepuPostService)).sheet().doRead();
        return ResponseDTO.succMsg("写入成功");
    }

    @WebLog(module = "bone-system")
    @PostMapping("users/import")
    @ApiOperation(value = "用户导入",notes = "")
    public ResponseDTO importUsers(MultipartFile file) throws IOException {
        EasyExcel.read(file.getInputStream(), UserImportDTO.class, new UserImportListener(sysUserService,sysDeptService)).sheet().doRead();
        return ResponseDTO.succMsg("写入成功");
    }


    @GetMapping("user/profile")
    @ApiOperation(value = "获取登录用户资料",notes = "需要请求头携带TOKEN")
    public ResponseDTO getUserProfile(){
        // 获取登录ID -- 只有登录态用户才可以调用
        Long loginId = StpUtil.getLoginIdAsLong();
        return getUser(loginId);
    }

    @WebLog(module = "bone-system")
    @PostMapping("users")
    @ApiOperation(value = "新增用户",notes = "")
    @SaCheckRole("admin")
    public ResponseDTO<SysUser> saveUser(@RequestBody @Validated UserAddDTO userAddDTO){
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(userAddDTO,sysUser,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        // userName 不允许重复
        Optional<SysUser> existOp = sysUserService.findByUserName(userAddDTO.getUserName());
        if (existOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.FORBIDDEN,"已存在相同用户名");
        }
        // 设置状态为启用
        sysUser.setStatus(1);
        // 获取首字母
        String initial = PinyinUtil.getFirstLetter(sysUser.getNickName(),"").substring(0,1);
        sysUser.setInitial(initial);
        return ResponseDTO.succData(sysUserService.saveOne(sysUser));
    }

    /**
     * 根据 userId 查询用户信息
     * @param userId
     * @return
     */
    @GetMapping("users/{userId}")
    @ApiOperation(value = "查询用户")
    @SaCheckPermission(value = "system_user:list",orRole = "admin")
    public ResponseDTO getUser(@PathVariable("userId") Long userId){
        Optional<SysUser> userOp = sysUserService.getById(userId);
        if(!userOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }else {
            SysUserVO sysUserVO = new SysUserVO();
            BeanUtil.copyProperties(userOp.get(),sysUserVO,CopyOptions.create().setIgnoreError(true).setIgnoreNullValue(true));
            Long deptId = userOp.get().getDeptId();
            Optional<SysDept> sysDeptOp = sysDeptService.getById(deptId);
            if(sysDeptOp.isPresent()){
                SysDeptVO sysDeptVO = new SysDeptVO();
                BeanUtil.copyProperties(sysDeptOp.get(),sysDeptVO,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
                sysUserVO.setSysDeptVO(sysDeptVO);
            }
            return ResponseDTO.succData(sysUserVO);
        }
    }

    @GetMapping("users/{userId}/basic")
    @ApiOperation(value = "查询用户基础信息(无需校验)")
    public ResponseDTO<SysUserBasic> getUserBasic(@PathVariable("userId") Long userId){
        Optional<SysUser> userOp = sysUserService.getById(userId);
        if (!userOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        Long deptId = userOp.get().getDeptId();

        SysUser user = userOp.get();
        SysUserBasic basic = new SysUserBasic();

        BeanUtil.copyProperties(user,basic,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Optional<SysDept> sysDeptOp = sysDeptService.getById(deptId);
        sysDeptOp.ifPresent(sysDept -> basic.setDeptName(sysDept.getDeptName()));
        return ResponseDTO.succData(basic);
    }



    @WebLog(module = "bone-system",operate = MethodTypeConst.UPDATE)
    @PutMapping("users")
    @SaCheckPermission(value = "system_user:update",orRole = "admin")
    @ApiOperation(value = "更新用户信息",notes = "传入对应数值，更新对应信息")
    public ResponseDTO<SysUser> updateUser(@RequestBody @Validated UserUpdateDTO userUpdateDTO){
        Optional<SysUser> sysUserOp = sysUserService.getById(userUpdateDTO.getId());
        if(!sysUserOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"传入ID错误");
        }
        SysUser sysUser = sysUserOp.get();
        //覆盖部分内容
        BeanUtil.copyProperties(userUpdateDTO,sysUser,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        // 获取首字母
        String initial = PinyinUtil.getFirstLetter(sysUser.getNickName(),"").substring(0,1);
        sysUser.setInitial(initial);
        return ResponseDTO.succData(sysUserService.updateOne(sysUser));
    }


    @WebLog(module = "bone-system",operate = MethodTypeConst.UPDATE)
    @PutMapping("user/update")
    @SaCheckPermission(value = "system_user:update",orRole = "admin")
    @ApiOperation(value = "更新用户岗位")
    public ResponseDTO<SysUser> updateUserPost(@RequestParam(value = "userId") Long userId,
                                               @RequestParam(value = "postId") String postId){
        Optional<SysUser> sysUserOp = sysUserService.getById(userId);
        if(!sysUserOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.ERROR_PARAM,"传入ID错误");
        }
        SysUser sysUser = sysUserOp.get();
        sysUser.setPostId(postId);
        return ResponseDTO.succData(sysUserService.updateOne(sysUser));
    }

    @GetMapping("users")
    @ApiOperation(value = "查询用户列表")
    @SaCheckPermission(value = "system_user:list",orRole = "admin")
    public ResponseDTO getUsers(UserQueryDTO userQueryDTO){
        Sort sort;
        if(userQueryDTO.getOrder().equalsIgnoreCase("DESC")){
            sort = Sort.by(Sort.Direction.DESC, userQueryDTO.getSortBy());
        }else {
            sort = Sort.by(Sort.Direction.ASC, userQueryDTO.getSortBy());
        }

        // tips : 页码对应 - 1
        Pageable pageable = PageRequest.of(userQueryDTO.getPageNum() - 1 , userQueryDTO.getPageSize(), sort);
        /**
         * 构建Example
         */
        SysUser sysUser = new SysUser();
        BeanUtil.copyProperties(userQueryDTO,sysUser,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
        Example<SysUser> example = Example.of(sysUser);
        //@TODO Example 查询需要使用containing 查询祖先节点是否包含 deptId
        return ResponseDTO.succData(sysUserService.getAll(pageable,example));
    }

    @GetMapping("users/groupByDept")
    @ApiOperation(value = "按(部门)分组用户")
    public ResponseDTO getUsersGroupByDept(){
        List<UserBaseVO> userBaseVOList = sysUserService.getAllUserBase();
        // 构建部门ID 列表
        Set<Long> deptIds = new HashSet<>();
        userBaseVOList.forEach(ele->{
            deptIds.add(ele.getDeptId());
        });
        // 根据ID 列表查询
        List<SysDept> depts = sysDeptService.findByIds(new ArrayList<>(deptIds));
        List<DeptUserTreeVO> deptUserTreeVOList = new ArrayList<>();
        for (SysDept dept:depts){
            DeptUserTreeVO item = new DeptUserTreeVO();
            BeanUtil.copyProperties(dept,item,CopyOptions.create().setIgnoreError(true).setIgnoreError(true));
            item.setLabel(dept.getDeptName());
            item.setValue(dept.getId());
            item.setDeptId(dept.getId());
            Set<UserBaseVO> userSet = new HashSet<>();
            for (UserBaseVO base:userBaseVOList){
                if (base.getDeptId().equals(dept.getId())){
                    base.setLabel(base.getNickName());
                    base.setValue(base.getId());
                    userSet.add(base);
                }
            }
            item.setChildren(new ArrayList<>(userSet));
            deptUserTreeVOList.add(item);
        }

        return ResponseDTO.succData(deptUserTreeVOList);
    }

    /**
     * 根据用户ID列表查询用户
     */
    @GetMapping("users/findByIds")
    @ApiOperation(value = "根据ID列表查询用户")
    public ResponseDTO getUserList(@RequestParam("userIds") List<Long> userIds){
        return ResponseDTO.succData(sysUserService.findByIds(userIds));
    }

    /**
     * 格局用户ID列表获取用户基础信息
     */
    @GetMapping("users/basic")
    @ApiOperation(value = "根据ID列表获取用户基础信息")
    public ResponseDTO<List<SysUserBasic>> getUserBasicList(@RequestParam("userIds") List<Long> userIds){
        List<SysUser> users = sysUserService.findByIds(userIds);
        List<Long> deptIds = new ArrayList<>();
        users.forEach(ele->{
            if (Validator.isNotEmpty(ele.getDeptId())){
                deptIds.add(ele.getDeptId());
            }
        });
        List<SysDept> depts = sysDeptService.findByIds(deptIds);
        List<SysUserBasic> basics = new ArrayList<>();
        for (SysUser user:users){
            SysUserBasic basic = new SysUserBasic();
            BeanUtil.copyProperties(user,basic,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
            for (SysDept dept:depts){
                if (dept.getId().equals(user.getDeptId())){
                    basic.setDeptName(dept.getDeptName());
                }
            }
            basics.add(basic);
        }
        return ResponseDTO.succData(basics);
    }


    @GetMapping("download")
    public ResponseDTO<String> download(HttpServletResponse response) throws IOException, ParseException {

        List<SysUser> exportList = new ArrayList<>();
        exportList = sysUserDAO.findAll();
        exportList = exportList.stream().filter(
                ele->ele.getDeptId()!=1
        ).collect(Collectors.toList());

        List<UserExportVO> list = new ArrayList<>();
        for (SysUser sysUser : exportList) {
            UserExportVO userExportVO = new UserExportVO();
            BeanUtil.copyProperties(sysUser,userExportVO, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
            if (sysUser.getDeptId()!=null){
                Optional<SysDept> optional = sysDeptDAO.findById(sysUser.getDeptId());
                if (!optional.isPresent()){
                    userExportVO.setDeptName("绑定部门不存在！");
                }else {
                    userExportVO.setDeptName(optional.get().getDeptName());
                }
            }else {
                userExportVO.setDeptName("未绑定所属部门！");
            }
            if (sysUser.getPostId()!=null){
                Optional<NepuPost> postOp = nepuPostDAO.findById(sysUser.getPostId());
                if (!postOp.isPresent()){
                    userExportVO.setPost("绑定岗位不存在！");
                    userExportVO.setPostType("绑定类型不存在！");
                }else {
                    userExportVO.setPost(postOp.get().getPostLevel()+":"+postOp.get().getPostGrade());
                    userExportVO.setPostType(postOp.get().getPostType());
                }
            }else {
                userExportVO.setPost("未绑定岗位！");
                userExportVO.setPostType("未绑定类型！");
            }
            list.add(userExportVO);
        }
        String filePath = fileParentPath+"userExportVO";
        String str =  System.currentTimeMillis()+"人员信息.xlsx";
        String fileName = filePath+ File.separator+str;
        FileUtil.touch(fileName);
        EasyExcel.write(fileName, UserExportVO.class).sheet("test").doWrite(list);
        log.info("执行完成");
        return ResponseDTO.succData("执行完成");
    }

//    @GetMapping(value = {"getInfo","self"})
//    @ApiOperation("获取登录用户信息")
//    public ResponseDTO getUser(){
//        //
//        Long userId = StpUtil.getLoginIdAsLong();
//        if(Validator.isEmpty(userId)){
//            return ResponseDTO.wrap(ResponseCodeConst.UNAUTHORIZED);
//        }
//        Optional<SysUser> sysUserOp = sysUserService.getById(userId);
//        if(!sysUserOp.isPresent()){
//            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"ID:["+userId+"]对应用户不存在");
//        }
//        LoginUserVO loginUserVO = new LoginUserVO();
//        BeanUtil.copyProperties(sysUserOp.get(),loginUserVO, CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
//        /**
//         * 获取部门ID
//         */
//        Long deptId = sysUserOp.get().getDeptId();
//        Optional<SysDept> sysDeptOp = sysDeptService.getOneDept(deptId);
//        /**
//         * 获取权限列表
//         */
//
//
//        if(sysDeptOp.isPresent())
//            loginUserVO.setSysDept(sysDeptOp.get());
//        return ResponseDTO.succData(loginUserVO);
//    }
//    @PutMapping("users/{userId}/roles/{roleId}")
//    @ApiOperation(value = "角色赋权")
//    public ResponseDTO grantUserRole(@PathVariable("userId") Long userId,@PathVariable("roleId") Long roleId){
//        return sysUserRoleService.grantUserRole(userId,roleId);
//    }




    /**
     * 查询当前用户角色
     */
    @GetMapping("users/{userId}/roles")
    @ApiOperation(value = "获取当前用户角色",notes = "")
    @SaCheckPermission(value = "system_user:list",orRole = "admin")
    public ResponseDTO getUserRoles(@PathVariable("userId") Long userId){
        Optional<SysUser> sysUserOp = sysUserService.getById(userId);
        if(!sysUserOp.isPresent()) {
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
        }
        SysUser sysUser = sysUserOp.get();
        return ResponseDTO.succData(sysUser.getRoles());
    }


    /**
     * 查询当前用户授权角色列表
     */
//    @GetMapping("users/{userId}/authRoles")
//    @ApiOperation(value = "获取当前用户授权角色",notes = "")
//    public ResponseDTO getUserAuthRoles(@PathVariable("userId") Long userId){
//        RoleAuthVO roleAuthVO = new RoleAuthVO();
//        List<SysRole> roles = sysRoleService.getAll();
//        Optional<SysUser> sysUserOp = sysUserService.getById(userId);
//        if(!sysUserOp.isPresent())
//            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND);
//        SysUserVO sysUserVO = new SysUserVO();
//        BeanUtil.copyProperties(sysUserOp.get(),sysUserVO,CopyOptions.create().setIgnoreNullValue(true).setIgnoreError(true));
//        roleAuthVO.setRoles(roles);
//        roleAuthVO.setUser(sysUserVO);
//        return ResponseDTO.succData(roleAuthVO);
//    }
    /*
     * 删除对应用户
     */
    @WebLog(module = "bone-system",operate = MethodTypeConst.DELETE)
    @DeleteMapping("users/{userId}")
    @ApiOperation(value = "删除单个用户")
    @SaCheckPermission(value = "system_user:delete",orRole = "admin")
    public ResponseDTO deleteUser(@PathVariable("userId") Long userId){
        return sysUserService.deleteById(userId);
    }


    //字段类型修改接口



    /**
     * 修改用户状态
     */
    @WebLog(module = "bone-system",operate = MethodTypeConst.UPDATE)
    @ApiIgnore
    @PutMapping("users/{userId}/status/{status}")
    @ApiOperation(value = "切换用户状态",notes = "")
    @SaCheckPermission(value = "system_user:update",orRole = "admin")
    public ResponseDTO updateUserStatus(@PathVariable("userId") Long userId,@PathVariable("status") Integer status){
        Optional<SysUser> sysUserOp = sysUserService.getById(userId);
        if(!sysUserOp.isPresent()){
            return ResponseDTO.wrap(ResponseCodeConst.NOT_FOUND,"ID:["+userId+"]对应用户不存在！");
        }
        SysUser sysUser = sysUserOp.get();
        sysUser.setStatus(status);
        //更新用户状态
        return ResponseDTO.succData(sysUserService.updateOne(sysUser));
    }

    /**
     * 重置用户密码
     */
    @WebLog(module = "bone-system",operate = MethodTypeConst.UPDATE)
    @PutMapping("users/{userId}/password/{password}")
    @ApiOperation(value = "重置用户密码",notes = "参数以路径形式传递")
    public ResponseDTO resetUserPassword(@PathVariable("userId") Long userId,@PathVariable("password") String password){
        return sysUserService.resetUserPassword(userId,password);
    }

}
